﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Abp.Application.Services.Dto;
using Abp.Domain.Repositories;
using ABP.Study.Tasks.Dtos;
using AutoMapper;
using Abp.AutoMapper;
using Abp.Dependency;
using Abp.Events.Bus;
using Abp.Events.Bus.Handlers;
using Abp.Timing;
using ABP.Study.Authorization.Users;

namespace ABP.Study.Tasks
{
    public class TaskAppService: StudyAppServiceBase, ITaskAppService
    {
        public IEventBus EventBus { get; set; }

        private readonly IRepository<Task> _taskRepository;
        /// <summary>
        ///In constructor, we can get needed classes/interfaces.
        ///They are sent here by dependency injection system automatically.
        /// </summary>
        public TaskAppService(IRepository<Task> taskRepository)
        {
            _taskRepository = taskRepository;
            EventBus = NullEventBus.Instance;
        }

        public GetTasksOutput GetTasks(GetTasksInput input)
        {
            var query = _taskRepository.GetAll();
            if (input.AssignedPersonId.HasValue)
            {
                query = query.Where(t => t.AssignedPersonId == input.AssignedPersonId.Value);
            }
            if (input.State.HasValue)
            {
                query = query.Where(t => t.State == input.State.Value);
            }
            return new GetTasksOutput
            {
                Tasks=Mapper.Map<List<TaskDto>>(query.ToList())
            };
        }

        public PagedResultDto<TaskDto> GetPagedTasks(GetTasksInput input)
        {
            throw new NotImplementedException();
        }

        public void UpdateTask(UpdateTaskInput input)
        {
            Logger.Info("Updating a task for input: " + input);
            var task = _taskRepository.Get(input.Id);
            if (input.State.HasValue)
            {
                task.State = input.State.Value;
            }
            //We even do not call Update method of the repository.
            //Because an application service method is a 'unit of work' scope as default.
            //ABP automatically saves all changes when a 'unit of work' scope ends (without any exception).
        }

        public int CreateTask(CreateTaskInput input)
        {
            //We can use Logger, it's defined in ApplicationService class.
            Logger.Info("Creating a task for input: " + input);

            //Creating a new Task entity with given input's properties
            var task = new Task
            {
                Description = input.Description,
                Title = input.Title,
                State = input.State,
                CreationTime = Clock.Now
            };
            EventBus.Trigger(new TaskCompletedEventData { TaskId = 42 });
            EventBus.Trigger<TaskCompletedEventData>(new TaskCompletedEventData{TaskId = 42});
            EventBus.Trigger(this, new TaskCompletedEventData { TaskId = 42 });
            EventBus.Trigger(typeof(TaskCompletedEventData), this, new
            TaskCompletedEventData
            { TaskId = 42 });
            return _taskRepository.InsertAndGetId(task);
        }

       


        public async Task<TaskDto> GetTaskByIdAsync(int taskId)
        {
            //Called specific GetAllWithPeople method of task repository.
            var task = await _taskRepository.GetAsync(taskId);

            //Used AutoMapper to automatically convert List<Task> to List<TaskDto>.
            return task.MapTo<TaskDto>();
        }

        public TaskDto GetTaskById(int taskId)
        {
            var task = _taskRepository.Get(taskId);

            return task.MapTo<TaskDto>();
        }

        public void DeleteTask(int taskId)
        {
            var task = _taskRepository.Get(taskId);
            if (task != null)
            {
                _taskRepository.Delete(task);
            }
        }

        public TaskCacheItem GetTaskFromCacheById(int taskId)
        {
            throw new NotImplementedException();
        }

        public IList<TaskDto> GetAllTasks()
        {
            throw new NotImplementedException();
        }

        public void Demo()
        {
            // 注册一个事件
            var registration = EventBus.Register<TaskCompletedEventData>(eventData
                => WriteActivity("A task is completed by id = " + eventData.TaskId));
            //取消注册一个事件
            registration.Dispose();

            //创建一个处理器
            var handler = new ActivityWriter();
            //注册一个事件
            EventBus.Register<TaskCompletedEventData>(handler);
            //取消这个事件的注册
            EventBus.Unregister<TaskCompletedEventData>(handler);

        }

        public static void WriteActivity(string org)
        {

        }

    }

    public class TaskCompletedEventData : EventData
    {
        public int TaskId { get; set; }
        public User CompletorUser { get; set; }
    }

    public class TaskEventData : EventData
    {
        public Task Task { get; set; }
    }
    public class TaskCreatedEventData : TaskEventData
    {
        public User CreatorUser { get; set; }
    }



    public class ActivityWriter : IEventHandler<TaskCompletedEventData>, IEventHandler<TaskCreatedEventData>,
        ITransientDependency
    {
        public void HandleEvent(TaskCompletedEventData eventData)
        {

            TaskAppService.WriteActivity("A task is completed by id = " +
                          eventData.TaskId);
        }

        public void HandleEvent(TaskCreatedEventData eventData)
        {
            throw new NotImplementedException();
        }
    }


}
